package com.zzgc.common.utils;

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Map;

/**
 * @ClassName ZxingUtils(Googel 二维码生成工具)
 * @Description 二维码相关
 * @author john
 * @Date 2016年12月6日 下午2:59:49
 * @version 1.0.0
 */
@Slf4j
public class ZxingUtils {

    //private static Log log = LogFactory.getLog(QRCodeUtils.class);

    private static final int BLACK = 0xFF000000;
    private static final int WHITE = 0xFFFFFFFF;


    /**
     * 裁剪图片
     *
     * @param bufferedImage 原始图片
     * @return java.awt.image.BufferedImage
     */
    public static BufferedImage cropImage(BufferedImage bufferedImage) {
        /*
         * 原始的二维码图片无论怎么设置都是有内边距的，但是二维码是双色图，最外部的就是需要切剪掉的颜色。所以我们取到x,y 轴  = 0的第一个色值
         * 然后逐次循环到左上方码眼位置。这个码眼位置就是我们需要切割的起始位置。x,y轴循环的次数就是我们需要切割的图片的宽高的二分之一。
         *
         * 我们的二维码创建都是正方形的，这里也有好处，省略了计算不同宽高的复杂过程
         * 【描述纯属抽象，example for this !】
         */
        int cropColor = bufferedImage.getRGB(0, 0);
        int width = 0, height = 0;
        label:
        for (int i = 0; i < bufferedImage.getWidth(); i++) {
            for (int j = 0; j < bufferedImage.getHeight(); j++) {
                if (bufferedImage.getRGB(i, j) != cropColor) {
                    width = i;
                    height = j;
                    break label;
                }
            }
        }
        //多预留1px
        width--;
        height--;
        //裁剪图片时留下1像素点的位置，光秃秃的实在难看
        bufferedImage = bufferedImage.getSubimage(width, height, bufferedImage.getWidth() - (width * 2), bufferedImage.getHeight() - (height * 2));
        return bufferedImage;
    }

    /**
     * 将一个BitMatrix对象转换成BufferedImage对象
     *
     * @param matrix
     * @return
     */
    private static BufferedImage toBufferedImage(BitMatrix matrix) {
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
            }
        }
        return image;
    }

    /**
     * 将BufferedImage对象输出到指定的文件中。
     *
     * @param image
     * @param destFile
     * @throws IOException
     */
    private static void writeToFile(BitMatrix matrix, String format, File file) throws IOException {
        BufferedImage image = toBufferedImage(matrix);
        image = cropImage(image);
        if (!ImageIO.write(image, format, file)) {
            throw new IOException("Could not write an image of format " + format + " to " + file);
        }
    }

    /**
     * 将内容contents生成长宽均为width的图片，图片路径由imgPath指定
     */
    public static File getQRCodeImge(String contents, int width, String imgPath) {
        return getQRCodeImge(contents, width, width, imgPath);
    }

    /**
     * 将内容contents生成长为width，宽为width的图片，图片路径由imgPath指定
     */
    public static File getQRCodeImge(String contents, int width, int height, String imgPath) {
        try {
            Map<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
            hints.put(EncodeHintType.CHARACTER_SET, "UTF8");

            BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, width, height, hints);

            File imageFile = new File(imgPath);
            writeToFile(bitMatrix, "png", imageFile);

            return imageFile;

        } catch (Exception e) {
            log.error("create QR code error!", e);
            return null;
        }
    }
   /* public static void main(String[] args) {
    	//ZxingUtils.getQRCodeImge("http://139.129.99.69:8022/examination/video/123.mp4", 500, 100,"D:/video/img");
    	//ZxingUtils.generateBarCode128("123456789","100","50");
    	BufferedImage encodeBarcode = ZxingUtils.encodeBarcode("hah",10,5);
    }*/
    /**
     * 128条形码
     *
     * @param strBarCode
     *            条形码：0-100位
     * @param dimension
     *            商品条形码：尺寸
     * @param barheight
     *            商品条形码：高度
     * @return 图片(Base64编码)
     */
//      public static String generateBarCode128(String strBarCode, String dimension, String barheight) {
//
//
//            try {
//                ByteArrayOutputStream outputStream = null;
//                BufferedImage bi = null;
//                int len = strBarCode.length();
//                JBarcode productBarcode = new JBarcode(Code128Encoder.getInstance(),
//                        WidthCodedPainter.getInstance(),
//                        EAN13TextPainter.getInstance());
//
//                // 尺寸，面积，大小 密集程度
//                productBarcode.setXDimension(Double.valueOf(dimension).doubleValue());
//                // 高度 10.0 = 1cm 默认1.5cm
//                productBarcode.setBarHeight(Double.valueOf(barheight).doubleValue());
//                // 宽度
//                productBarcode.setWideRatio(Double.valueOf(30).doubleValue());
////                  是否显示字体
//                productBarcode.setShowText(true);
////                 显示字体样式
//                productBarcode.setTextPainter(BaseLineTextPainter.getInstance());
//
//                // 生成二维码
//                bi = productBarcode.createBarcode(strBarCode);
//
//                outputStream = new ByteArrayOutputStream();
//                ImageIO.write(bi, "jpg", outputStream);
//                BASE64Encoder encoder = new BASE64Encoder();
////            System.err.println(encoder.encode(outputStream.toByteArray()));
//
//                return encoder.encode(outputStream.toByteArray());
//            } catch (Exception e) {
//                e.printStackTrace();
//                return "encodeError";
//            }
//        }

      private static final int IMAGE_WIDTH = 80;
      private static final int IMAGE_HEIGHT = 80;
      private static final int IMAGE_HALF_WIDTH = IMAGE_WIDTH / 2;
      private static final int FRAME_WIDTH = 2;
      /**
       * 生成条形码
       * @param contents 条形码内容
       * @param width 条形码宽度
       * @param height 条形码高度
       * @return
       */
      public static BufferedImage encodeBarcode(String contents, int width, int height){
          int codeWidth = 3 + // start guard
                  (7 * 6) + // left bars
                  5 + // middle guard
                  (7 * 6) + // right bars
                  3; // end guard
          codeWidth = Math.max(codeWidth, width);
          BufferedImage barcode = null;
          try {
              BitMatrix bitMatrix = new MultiFormatWriter().encode(contents,BarcodeFormat.EAN_13, codeWidth, height, null);
             barcode= MatrixToImageWriter.toBufferedImage(bitMatrix);
          } catch (Exception e) {
              e.printStackTrace();
          }
          return barcode;
      }
      /**
       * 解析读取条形码
       * @param barcodePath 条形码文件路径
       * @return
       */
      public static String decodeBarcode(String barcodePath){
          BufferedImage image;
          Result result = null;
          try {
              image = ImageIO.read(new File(barcodePath));
              if (image != null) {
                   LuminanceSource source = new BufferedImageLuminanceSource(image);
                  BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
                  result = new MultiFormatReader().decode(bitmap, null);
              }
              return result.getText();
          } catch (Exception e) {
              e.printStackTrace();
          }
          return null;
      }
      //测试
      /*public static void main(String[] args) {
          try {
              //Create the barcode bean
              Code39Bean bean = new Code39Bean();

              final int dpi = 150;

              //Configure the barcode generator
              bean.setModuleWidth(UnitConv.in2mm(1.0f / dpi)); //makes the narrow bar
                                                               //width exactly one pixel
              bean.setWideFactor(3);
              bean.doQuietZone(false);

              //Open output file
              File outputFile = new File("d:\\out.png");
              OutputStream out = new FileOutputStream(outputFile);
              try {
                  //Set up the canvas provider for monochrome JPEG output
                  BitmapCanvasProvider canvas = new BitmapCanvasProvider(
                          out, "image/png", dpi, BufferedImage.TYPE_BYTE_BINARY, false, 0);

                  //Generate the barcode
                  bean.generateBarcode(canvas, "A123456");

                  //Signal end of generation
                  canvas.finish();
              } finally {
                  out.close();
              }
          } catch (Exception e) {
              e.printStackTrace();
          }
      }*/
      public static void main(String[] paramArrayOfString) {
          String contents = "http://wuzhen71.f3322.net:8000/vision/equipment/optometer";
          String imgPath = "D:\\lgl\\data\\wuzhen71.jpg";
          File qrCodeImge = getQRCodeImge(contents, 200, imgPath);
          System.out.println("qrCodeImge.getName() = " + qrCodeImge.getPath());
          String s = decodeBarcode(imgPath);
          System.out.println("s = " + s);
//    	           try {
//    	               JBarcode localJBarcode = new JBarcode(EAN8Encoder.getInstance(),WidthCodedPainter.getInstance(),EAN8TextPainter.getInstance());
//    	              String str = "2017061";
//    	             /* localJBarcode.setShowCheckDigit(false);
//    	              localJBarcode.setShowText(true);//显示图片下字符串内容
//    	              localJBarcode.setShowCheckDigit(false);//显示字符串内容中是否显示检查码内容
//    	              localJBarcode.setCheckDigit(false);//不生成检查码
//*/
//
//    	              BufferedImage localBufferedImage = localJBarcode.createBarcode(str);
//
//    	               saveToJPEG(localBufferedImage, "EAN8123.jpg");
//    	           }
//    	           catch (Exception localException) {
//    	               localException.printStackTrace();
//    	           }
    	       }

//    	       static void saveToJPEG(BufferedImage paramBufferedImage, String paramString) {
//    	           saveToFile(paramBufferedImage, paramString, "jpeg");
//    	       }

//    	       static void saveToFile(BufferedImage paramBufferedImage, String paramString1, String paramString2) {
//    	           try {
//    	               FileOutputStream localFileOutputStream = new FileOutputStream("D:/" + paramString1);
//    	               ImageUtil.encodeAndWrite(paramBufferedImage, paramString2, localFileOutputStream, 96, 96);
//    	               localFileOutputStream.close();
//    	              /* scale(paramString1,2);*/
//    	           }
//    	          catch (Exception localException) {
//    	               localException.printStackTrace();
//    	          }
//    	       }
    	       /**
    	   	 * 等比例放大图象
    	   	 *
    	   	 * @param imgUrl 图像路径
    	   	 * @param resultImgUrl 放大后的存放路径
    	   	 * @param scale 放大倍数
    	   	 * @throws IOException
    	   	 */
    	   	static void scale(String paramString1, int scale)
    	   			throws IOException {
    	   		BufferedImage src = ImageIO.read(new File("D:/" + paramString1));
    	   		int width = src.getWidth();
    	   		int height = src.getHeight();

    	   		width = width * scale;
    	   		height = height * scale;

    	   		Image image = src.getScaledInstance(width, height, Image.SCALE_DEFAULT);
    	   		BufferedImage tag = new BufferedImage(width, height,
    	   				BufferedImage.TYPE_INT_RGB);
    	   		Graphics g = tag.getGraphics();
    	   		g.drawImage(image, 0, 0, null);
    	   		g.dispose();
    	   		ImageIO.write(tag, "JPEG", new File("D:/" + paramString1));
    	   	}
}
